package org.budo.graph.druid.dubbo.filter;

import org.budo.graph.Constant;
import org.budo.support.slf4j.Slf4j;
import org.budo.support.spring.context.aware.BudoApplicationContextAware;
import org.slf4j.Logger;

import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.extension.Activate;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;

/**
 * Dubbo客户端发起调用时，附带上本地端信息
 * 
 * @author lmw
 */
@Activate(group = { Constants.CONSUMER })
public class BudoGraphDruidDubboConsumerSideFilter extends AbstractBudoGraphDruidDubboFilter implements Filter {
    private static final Logger log = Slf4j.getLogger();

    private String remoteAddress;

    private String sessionId;

    private String userAgent;

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        RpcContext context = RpcContext.getContext();

        context.setAttachment(Constant.DruidDubbo.SESSION_ID_KEY, this.getSessionId(invoker, invocation));
        context.setAttachment(Constant.DruidDubbo.REMOTE_ADDRESS_KEY, this.getRemoteAddress());
        context.setAttachment(Constant.DruidDubbo.USER_AGENT_KEY, this.getUserAgent());

        return invoker.invoke(invocation);
    }

    private String getUserAgent() {
        if (null == this.userAgent || this.userAgent.trim().isEmpty()) {
            this.userAgent = this.buildUserAgent();
        }

        return this.userAgent;
    }

    private String getSessionId(Invoker<?> invoker, Invocation invocation) {
        if (null != this.sessionId && !this.sessionId.trim().isEmpty()) { // 如果非空就直接返回
            return this.sessionId;
        }

        // 如果BudoApplicationContextAware为空，构建这个值并返回，不缓存
        BudoApplicationContextAware applicationContextAware = BudoApplicationContextAware.getInstance();
        if (null == applicationContextAware) { // 程序启动过程中
            log.error("#60 BudoApplicationContextAware.getInstance is null now, invoker.interface=" + (null == invoker ? "null-invoker" : invoker.getInterface()) //
                    + ", invocation.methodName=" + (null == invocation ? "null-invocation" : invocation.getMethodName()));

            return this.buildSessionId(); // 不写入属性，会每次重复构建
        }

        this.sessionId = this.buildSessionId(); // 如果sessionId为空，而BudoApplicationContextAware不为空
        return this.sessionId; // 构建并缓存这个值，只会执行一次
    }

    private String getRemoteAddress() {
        if (null == this.remoteAddress || this.remoteAddress.trim().isEmpty()) {
            this.remoteAddress = this.buildRemoteAddress();
        }

        return this.remoteAddress;
    }
}